SYSSIZE     equ 0x7f00
SETUPLEN    equ 4
BOOTSEG     equ 0x07c0
INITSEG     equ 0x9000
SETUPSEG    equ 0x9020
SYSSEG      equ 0x1000
ENDSEG      equ SYSSEG + SYSSIZE

start:
    mov ax, BOOTSEG
    mov ds, ax
    mov ax, INITSEG
    mov es, ax
    mov cx, 256
    sub si, si
    sub di, di
    rep
    movsw           ; 将bootsect.s从0x7c00移动到0x90000
    jmp INITSEG:go
go: mov ax, cs
    mov dx, 0x4000 - 12

    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, dx      ; 设置栈地址INITSEG:0x4000-12

load_setup:
    mov dx, 0x00
    mov cx, 0x02
    mov bx, 0x0200
    mov ax, 0x0200 + SETUPLEN
    int 0x13        ; 加载setup.s到0x90200
    jnc ok_load_setup   ; 读取成功则跳转
    mov dx, 0x00
    mov ax, 0x00
    int 0x13
    jmp load_setup  ; 加载失败则复位软盘，重新加载

ok_load_setup:
    mov ah, 0x03
    xor bh, bh
    int 0x10        ; 获取光标位置

    mov cx, 24      ; 写24个字符
    mov bx, 0x0007  ; 页面0，颜色模式7
    mov bp, msg     ; 字符串地址
    mov ax, 0x1301  ; 写字符串，光标随之移动
    int 0x10        ; 进入BIOS中断

    call    read_it ; 读取内核到内存中
    call    kill_motor  ; 关闭软盘驱动器

    jmp SETUPSEG:0  ; 跳转到setup.s的代码

read_it:
    mov ax, SYSSEG
    mov es, ax
    mov bx, 0
    mov cx, 0x06
    mov dx, 0x00
rp_read:
    mov ax, es
    cmp ax, ENDSEG      ; 是否读取完毕
    jb cont_read
    ret
cont_read:
    call read_sectors
    mov ax, es
    add ax, 0x200
    mov es, ax
    add cl, 16
    cmp cl, 18
    jbe rp_read         ; 若扇区号小于等于18，就无需切换磁头或磁道
    sub cl, 18
    xor dh, 1           ; 切换磁头
    jne rp_read
    add ch, 1           ; 切换磁道
    jmp rp_read

read_sectors:
    push dx
    mov ax, 0x210
    int 0x13
    jc bad_rt           ; 读取失败则跳转
    pop dx
    ret
bad_rt:
    mov dx, 0x00
    mov ax, 0x00
    int 0x13
    pop dx
    jmp read_sectors

kill_motor:
    push    dx
    mov dx, 0x3f2
    mov al, 0
    out dx, al
    pop dx
    ret

msg:                ; 要打印的字符串
    db 13, 10
    db "Loading system ..."
    db 13, 10, 13, 10

    times 0x1fe - ($ - $$) db 0 ; 填写0，直到0x1fe
    dw 0xaa55       ; 启动盘标识
